﻿#region using
using System;
using BlogEngine.Core.Web.Controls;
using BlogEngine.Core;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Data;
#endregion

[Extension("Adds SyntaxHighlighter scripts to your post pages. Designed for <a target=\"_blank\" href=\"http://alexgorbatchev.com/wiki/SyntaxHighlighter\">SyntaxHighlighter 2.0<a/>", "1.1", "<a target=\"_blank\" href=\"http://blog.soelsoft.dk\">Lasse Soelberg</a>")]
public class SyntaxHighlighter
{
    #region Private members

    private static ExtensionSettings brushes = null;
    private static ExtensionSettings folders = null;
    private static ExtensionSettings themes = null;

    private string extensionName = "SyntaxHighlighter";
    private static string scriptsFolder;
    private static string stylesFolder;

    #endregion

    #region Constructor

    /// <summary>
    /// Hook into the Post.Serving event.
    /// </summary>
    public SyntaxHighlighter()
    {
        BlogEngine.Core.Post.Serving += new EventHandler<ServingEventArgs>(AddSyntaxHighlighter);
        
        InitSettings();

    }

    #endregion

    #region Add SyntaxHighlighter elements to Page

    /// <summary>
    /// Adds the JavaScript and Css tags that are necesarry for the blog to utilise the 
    /// SyntaxHighlighter JavaScript classes.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void AddSyntaxHighlighter(object sender, ServingEventArgs e)
    {
        HttpContext context = HttpContext.Current;
        if (context.CurrentHandler is System.Web.UI.Page)
        {
            if (context.Items[extensionName] == null && scriptsFolder != null)
            {
                // Loads the settings
                brushes = ExtensionManager.GetSettings(extensionName, "Brushes");
                folders = ExtensionManager.GetSettings(extensionName, "Folders");
                themes = ExtensionManager.GetSettings(extensionName, "Styles");

                if (folders != null && brushes != null && themes != null)
                {
                    // prep page handler
                    System.Web.UI.Page page = (System.Web.UI.Page)context.CurrentHandler;

                    // Add core and legacy javascripts to the page header
                    page.Header.Controls.Add(JavaScriptInclude(scriptsFolder + "/shCore.js"));
                    page.Header.Controls.Add(JavaScriptInclude(scriptsFolder + "/shLegacy.js"));

                    // Adds the selected brushes to the page header
                    DataTable dt = brushes.GetDataTable();
                    object[] itemArray = dt.Rows[0].ItemArray;
                    for (int i = 0; i < dt.Columns.Count; i++)
                    {
                        if (itemArray[i].ToString() == "True")
                        {
                            page.Header.Controls.Add(JavaScriptInclude(scriptsFolder + "/" + dt.Columns[i].ColumnName));
                        }

                    }

                    // Add main stylesheet
                    HtmlLink mainCss = new HtmlLink();
                    mainCss.Attributes["type"] = "text/css";
                    mainCss.Attributes["rel"] = "stylesheet";
                    mainCss.Attributes["href"] = Utils.RelativeWebRoot + stylesFolder + "/shCore.css";
                    page.Header.Controls.Add(mainCss);

                    // Add theme stylesheet
                    HtmlLink themeCss = new HtmlLink();
                    themeCss.Attributes["type"] = "text/css";
                    themeCss.Attributes["rel"] = "stylesheet";
                    themeCss.Attributes["href"] = Utils.RelativeWebRoot + stylesFolder + "/" + themes.GetSingleValue("Style");
                    themeCss.Attributes["id"] = "shTheme";
                    page.Header.Controls.Add(themeCss);

                    // Build script syntax
                    HtmlGenericControl script = new HtmlGenericControl("script");
                    script.Attributes["type"] = "text/javascript";
                    script.InnerHtml = "SyntaxHighlighter.config.clipboardSwf = '" + Utils.RelativeWebRoot + scriptsFolder + "/clipboard.swf';SyntaxHighlighter.all();";
                    page.Header.Controls.Add(script);

                    // Finish up        
                    context.Items[extensionName] = 1;
                }
            }
        }
    }

    #endregion

    #region Initialise the extension

    /// <summary>
    /// Initialises the extension.
    /// If not set, the brushes and styles gets loaded dynamically.
    /// </summary>
    public void InitSettings()
    {
        
        // Initialising the folders
        ExtensionSettings folderSettings = new ExtensionSettings("Folders");
        folderSettings.IsScalar = true;
        folderSettings.AddParameter("Scripts");
        folderSettings.AddValue("Scripts", "SyntaxHighlighter/scripts");
        folderSettings.AddParameter("Styles");
        folderSettings.AddValue("Styles", "SyntaxHighlighter/styles");
        folderSettings.Help = "The path to the scripts and styles folders, relative to the blog's root";
        folders = ExtensionManager.InitSettings(this.GetType().Name, folderSettings);

        ExtensionManager.ImportSettings(this.GetType().Name, folders);
        scriptsFolder = folders.GetSingleValue("Scripts");
        stylesFolder = folders.GetSingleValue("Styles");

        // Initialising the brushes
        string brushInfo = "<br/><br/><font color=\"red\">The scripts folder could not be found.</font>";
        DirectoryInfo info = new DirectoryInfo(HttpContext.Current.Server.MapPath("~/" + scriptsFolder));
        if (!info.Exists)
        {
            // Couldn't find the scripts folder
            scriptsFolder = null;
            if (!folders.Help.Contains(brushInfo))
                folders.Help = folders.Help + brushInfo;
        }
        else
        {
            folders.Help = folders.Help.Replace(brushInfo, "");
            ExtensionSettings brushSettings = new ExtensionSettings("Brushes");
            brushSettings.IsScalar = true;
            brushSettings.Help = "Select the brushes that should be enabled on this blog." +
                "<br/><br/>Updating the list will reload the brushes from the scripts folder. This will reset all brushes to be enabled by default.";
            FileInfo[] files = info.GetFiles();
            foreach (FileInfo file in files)
            {
                if (file.Name.StartsWith("shBrush"))
                {
                    brushSettings.AddParameter(file.Name, file.Name.Replace("shBrush", "").Replace(".js", ""), 20, false, false, ParameterType.Boolean);
                    brushSettings.AddValue(file.Name, true);
                }
            }
            ExtensionManager.ImportSettings(this.GetType().Name, brushSettings);

        }

        // Initialising the themes
        string styleInfo = "<br/><br/><font color=\"red\">The styles folder could not be found.</font>";
        DirectoryInfo themeInfo = new DirectoryInfo(HttpContext.Current.Server.MapPath("~/" + stylesFolder));
        if (!themeInfo.Exists)
        {
            // Couldn't find the styles folder
            stylesFolder = null;
            if (!folders.Help.Contains(styleInfo))
                folders.Help = folders.Help + styleInfo;
        }
        else
        {
            folders.Help = folders.Help.Replace(styleInfo, "");
            ExtensionSettings styleSettings = new ExtensionSettings("Styles");
            styleSettings.IsScalar = true;
            styleSettings.Help = "Choose the style to use for SyntaxHighlighter." +
                "<br/><br/>Updating the list will reload all styles from the styles folder. Will reset the chosen style to the default style.";
            FileInfo[] files = themeInfo.GetFiles();
            foreach (FileInfo file in files)
            {
                if (file.Name.StartsWith("shTheme"))
                {
                    styleSettings.AddParameter(file.Name, file.Name.Replace("shTheme", "").Replace(".css", ""), 20, false, false, ParameterType.Boolean);
                    styleSettings.AddValue(file.Name, false);
                }
            }
            styleSettings.AddParameter("Style", "Style", 20, false, false, ParameterType.String);
            styleSettings.AddValue("Style", "shThemeDefault.css");
            ExtensionManager.ImportSettings(this.GetType().Name, styleSettings);
        }
        ExtensionManager.Save();

        // set page that Extension Manager will use  
        // instead of default settings page
        ExtensionManager.SetAdminPage(extensionName, "~/SyntaxHighlighter/Admin.aspx");
    }

    #endregion

    #region Private helper methods

    private HtmlGenericControl JavaScriptInclude(string url)
    {
        HtmlGenericControl script = new HtmlGenericControl("script");
        script.Attributes["type"] = "text/javascript";
        script.Attributes["src"] = ResolveScriptUrl(url);
        return script;
    }

    private string ResolveScriptUrl(string url)
    { return Utils.RelativeWebRoot + "js.axd?path=" + Utils.RelativeWebRoot + url; }

    #endregion
}

